package cn.brilliantfuture.commentry.order.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.UserTransaction;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.log4j.Logger;

import cn.brilliantfuture.commentry.entity.DeliveryPlan;
import cn.brilliantfuture.commentry.entity.ExpenseRecord;
import cn.brilliantfuture.commentry.entity.OrderInformation;
import cn.brilliantfuture.commentry.entity.OrderProductInfo;
import cn.brilliantfuture.commentry.entity.ProductBatch;
import cn.brilliantfuture.commentry.entity.StorageGrid;
import cn.brilliantfuture.commentry.entity.WorkflowInfo;
import cn.brilliantfuture.commentry.exception.DuplicateSubmitException;
import cn.brilliantfuture.commentry.order.OrderMessageLocal;
import cn.brilliantfuture.commentry.util.BarcodeMaker;
import cn.brilliantfuture.commentry.util.CommEntryUtil;
import cn.brilliantfuture.commentry.util.DateTimeHelper;
import cn.brilliantfuture.commentry.util.HttpUtil;

/**
 * 
 * Title: Communication Entry
 * 
 * Author:  LiTian  
 *
 * Date: 2012-3-29
 * 
 * Description:
 * 
 */
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class OrderMessageImpl implements OrderMessageLocal {
	
	private static Logger logger = Logger.getLogger(OrderMessageImpl.class);
	
	@PersistenceContext(unitName = "commentry-jpa")
	EntityManager entityManager;
	
	@Resource 
	SessionContext sessionContext;

	public boolean saveOrderInfo(OrderInformation orderInformation, List<OrderProductInfo> orderProductInfos) {
		
		UserTransaction ut = sessionContext.getUserTransaction();
		try {
			ut.begin();

			if (!isExistForOrder(orderInformation.getNumber())) {
				throw new DuplicateSubmitException();
			}
			
			entityManager.persist(orderInformation);
			entityManager.flush();
			
			for (OrderProductInfo orderProductInfo : orderProductInfos) {
				orderProductInfo.setOrderInformation(orderInformation);
				entityManager.persist(orderProductInfo);
			}
			
			WorkflowInfo workflowInfo = new WorkflowInfo();
			workflowInfo.setOrderInformation(orderInformation);
			workflowInfo.setWorkflowIndex(1);
			workflowInfo.setWorkflowType(1);
			workflowInfo.setOperator("会员");
			workflowInfo.setContent("会员完成商品订购...");
			workflowInfo.setInsertTime(new Date());
			workflowInfo.setInsertModel(2);
			Date orderTime = new Date();
			orderTime.setTime(orderInformation.getInsertTime().getTime() - 3000);
			workflowInfo.setWorkflowTime(orderTime);
			workflowInfo.setDeleted(false);
			entityManager.persist(workflowInfo);
			
			workflowInfo = new WorkflowInfo();
			workflowInfo.setOrderInformation(orderInformation);
			workflowInfo.setWorkflowIndex(2);
			workflowInfo.setWorkflowType(1);
			workflowInfo.setOperator("系统");
			workflowInfo.setContent("智能配送平台接收配送单...");
			workflowInfo.setInsertTime(new Date());
			workflowInfo.setInsertModel(2);
			workflowInfo.setWorkflowTime(orderInformation.getInsertTime());
			workflowInfo.setDeleted(false);
			entityManager.persist(workflowInfo);
			
			entityManager.flush();
			
			ut.commit();
			return true;
		} catch (Exception e) {
			logger.error("OrderMessageImpl.saveOrderInfo(OrderInformation orderInformation, List<OrderProductInfo> orderProductInfos)\n" + e.getMessage());
			try {
				ut.rollback();
			} catch (Exception e1) {
				logger.error("Data rollback fail!\n" + e1.getMessage());
			} 

			return false;
		} 
	}

	public boolean isExistForOrder(String orderCode) {
		String sql = "select count(oi.orderInformationId) as sum from OrderInformation oi where oi.number = '" + orderCode + "'";
		Object obj = entityManager.createQuery(sql).getSingleResult();
		
		if (Integer.parseInt(obj.toString()) == 0)
			return true;
		else	
			return false;
	}

	@SuppressWarnings({ "unchecked", "deprecation" })
	public String getRfidCode(String orderCode) {
		List<OrderInformation> orderInformations = entityManager.createQuery("select oi from OrderInformation oi where oi.number = '" + orderCode + "'").getResultList();
		if(null != orderInformations && orderInformations.size() > 0){
			
			OrderInformation orderInfo = orderInformations.get(0);
			
			if (orderInfo.getTransactions() == 1){
				
				int serialNum = 1;
				
				int groupId = orderInfo.getGroup().getGroupId();
				String groupSn = orderInfo.getGroup().getGroupSn();
				int lockersId = orderInfo.getLockers().getLockersId();
				String lockersSn = orderInfo.getLockers().getLockersSn();
				String deviceSn = orderInfo.getLockers().getDevice().getDeviceSn();
				String memberCode = orderInfo.getPurchaser().getCardInfo().getCardNumber();
				int dataModel = orderInfo.getStoreMode() < 3 ? 0 : orderInfo.getDataModels().getDataModelId() < 3 ? 3 : orderInfo.getDataModels().getDataModelId();
				
				Date beginTime = orderInfo.getDeliveryTime();
				Date endTime = orderInfo.getDeliveryEndTime();
				
				/*if (new Date().after(endTime)) {
					logger.info("Delivery time expire!");
					return null;
				}*/
				
				if ((beginTime.getHours() != 2 && endTime.getHours() != 8) || (beginTime.getHours() != 8 && endTime.getHours() != 14) || (beginTime.getHours() != 14 && endTime.getHours() != 20) || (beginTime.getHours() != 20 && endTime.getHours() != 2)) {
					Calendar calendar = Calendar.getInstance();
					calendar.setTime(beginTime);
					calendar.set(Calendar.HOUR_OF_DAY, 8);
					calendar.set(Calendar.MINUTE, 0);
					calendar.set(Calendar.SECOND, 0);
					orderInfo.setDeliveryTime(calendar.getTime());

					calendar.set(Calendar.HOUR_OF_DAY, 14);
					calendar.set(Calendar.MINUTE, 0);
					calendar.set(Calendar.SECOND, 0);
					orderInfo.setDeliveryEndTime(calendar.getTime());
				}
				
				DeliveryPlan deliveryPlan = planFilter(groupId, lockersId, orderInfo.getOrderInformationId(), 1, orderInfo.getStoreMode(), orderInfo.getDeliveryTime(), orderInfo.getDeliveryEndTime(), null);
				
				if (null == deliveryPlan){
					logger.info("Delivery plan filter fail!");
					return null;
				}
				
				ProductBatch productBatch = new ProductBatch();
				
				// 获取年份和当前天数
				Calendar calendar = Calendar.getInstance();
				calendar.setTime(orderInfo.getDeliveryTime());
				
				// 产生流水号
				List<String> rfidList = (List<String>) entityManager.createQuery("select productBatch.rfidSn from ProductBatch productBatch where productBatch.rfidSn like '___________" + CommEntryUtil.getFormatStr(String.valueOf(calendar.get(Calendar.DAY_OF_YEAR)), 3) + "_______________' order by productBatch.productBatchId desc").getResultList();

				// 获取下一个流水号编号,如果当天没有从00-01开始
				if (rfidList.size() > 0){
					serialNum = Integer.parseInt(rfidList.get(0).substring(14, 18)) + 1;
				}
				
				// 保存包装箱及开柜密码
				while (true) {
					JSONObject result = BarcodeMaker.getCode128v1DOT3(groupSn, lockersSn, orderInfo.getStoreMode(), dataModel, deliveryPlan.getStorageGrid().getGridNum(), serialNum, orderInfo.getDeliveryTime(), memberCode);
					String rfidSn = result.getString("rfidSn");
					String passwd = result.getString("passwd");
					List<ProductBatch> list = entityManager.createQuery("select pb from ProductBatch pb where pb.passwd = :passwd and (pb.orderInformation.transactions = 3 or pb.orderInformation.transactions = 6)").setParameter("passwd", passwd).getResultList();
					serialNum++;
					if (null == list || list.size() == 0) {
						serialNum = 1;
						productBatch.setRfidSn(rfidSn);
						productBatch.setPasswd(passwd);
						break;
					}
				}

				productBatch.setOrderInformation(orderInfo);
				orderInfo.setTransactions(3);

				productBatch.setInsertTime(new Date());
				productBatch.setStatus(0);

				UserTransaction ut = sessionContext.getUserTransaction();
				try {
					ut.begin();
					
					entityManager.merge(orderInfo);
					entityManager.persist(productBatch);
					
					deliveryPlan.setProductBatch(productBatch);
					deliveryPlan.setOrderInformation(orderInfo);
					
					entityManager.persist(deliveryPlan);
					
					entityManager.flush();
					
					ut.commit();
					
					StringBuffer sb = new StringBuffer();
					sb.append("http://127.0.0.1:8085/deliveryplan/?").append("deviceSn=");
					sb.append(deviceSn).append("&gridNum=").append(deliveryPlan.getStorageGrid().getGridNum());
					sb.append("&storeMode=").append(orderInfo.getStoreMode());
					sb.append("&rfidSn=").append(productBatch.getRfidSn());
					sb.append("&businessType=").append(1);
					sb.append("&beginTime=").append(DateTimeHelper.dateTimeToStr(orderInfo.getDeliveryTime(), "yyyyMMddHHmm")).append("&endTime=").append(DateTimeHelper.dateTimeToStr(orderInfo.getDeliveryEndTime(), "yyyyMMddHHmm"));
					sb.append("&planType=").append(1);
					
					logger.info(HttpUtil.getInvoke(sb.toString()));
					
					return productBatch.getRfidSn();
				} catch (Exception e) {
					try {
						ut.rollback();
					} catch (Exception e1) {
						logger.error("Data rollback fail!\n" + e1.getMessage());
					} 

					return null;
				}
			} else if (orderInfo.getTransactions() == 3){
				List<ProductBatch> productBatchs = new ArrayList<ProductBatch>(orderInfo.getProductBatchs());
				if (productBatchs.size() > 0) {
					return productBatchs.get(0).getRfidSn();
				} else {
					return null;
				}
			} else {
				return null;
			}
				
		} else {
			return null;
		}
			
	}

	@SuppressWarnings("unchecked")
	public boolean modfiyRefundOrderState(String orderOcde) {
		UserTransaction ut = sessionContext.getUserTransaction();
		
		try {
			ut.begin();
			
			List<OrderInformation> list = entityManager.createQuery("select oi from OrderInformation oi where oi.deleted = 0 and oi.effective = 1 and oi.number = '" + orderOcde + "'").getResultList();
			
			if (null == list || list.size() == 0)
				throw new Exception();
				
			OrderInformation orderInfo = list.get(0);
			
			if (orderInfo.getPaymentMode() == 5){
				List<ExpenseRecord> recordList = entityManager.createQuery("select er from ExpenseRecord er where er.type = 2 and er.orderCode = '" + orderInfo.getNumber() + "' and er.purchaserId = " + orderInfo.getPurchaser().getPurchaserId()).getResultList();
				
				if (null == recordList || recordList.size() == 0)
					throw new Exception();
			}
			
			orderInfo.setEffective(false);
			
			entityManager.merge(orderInfo);
			
			entityManager.flush();
			
			ut.commit();
			
			return true;
		} catch (Exception e) {
			logger.error("modfiyRefundOrderState(String orderOcde)\n" + e.getMessage());
			try {
				ut.rollback();
			} catch (Exception e1) {
				logger.error("Data rollback fail!\n" + e1.getMessage());
			} 
			return false;
		}
		
	}

	@SuppressWarnings("unchecked")
	public Integer queryOrderState(String orderOcde) {
		List<OrderInformation> list = entityManager.createQuery("select oi from OrderInformation oi where deleted = 0 and number = '" + orderOcde + "'").getResultList();
		
		if (null != list && list.size() > 0)
			return list.get(0).getTransactions();
		
		return null;
	}

	@SuppressWarnings({ "unchecked", "deprecation" })
	public JSONArray[] getRfidCodes(String orderCode, int generalNum, int keepWarmNum, int thermostatNum) {
		JSONArray[] results = new JSONArray[3];

		UserTransaction ut = sessionContext.getUserTransaction();
		
		try {
			ut.begin();
			
			List<OrderInformation> orderInformations = entityManager.createQuery("select oi from OrderInformation oi where oi.number = '" + orderCode + "'").getResultList();
			
			if(null != orderInformations && orderInformations.size() > 0){
				
				OrderInformation orderInfo = orderInformations.get(0);
				
				if (orderInfo.getTransactions() == 1){
					
					int serialNum = 1;
					
					// 获取年份和当前天数
					Calendar calendar = Calendar.getInstance();
					calendar.setTime(new Date());

					String year = DateTimeHelper.dateTimeToStr(calendar.getTime(), "yy");
					String days = CommEntryUtil.getFormatStr(String.valueOf(calendar.get(Calendar.DAY_OF_YEAR)), 3);
					
					// 产生流水号
					List<String> rfidList = (List<String>) entityManager.createQuery("select productBatch.rfidSn from ProductBatch productBatch where productBatch.rfidSn like '_________" + year + days + "_______________' order by productBatch.productBatchId desc").getResultList();

					if (rfidList.size() > 0){
						serialNum = Integer.parseInt(rfidList.get(0).substring(14, 18)) + 1;
					}

					JSONArray generalCodes = new JSONArray();
					
					for (int i = 0; i < generalNum; i++) {
						ProductBatch productBatch = new ProductBatch();
						productBatch.setOrderInformation(orderInfo);
						
						// 保存包装箱及开柜密码
						while (true) {
							JSONObject result = BarcodeMaker.getCode128(orderInfo.getGroup().getGroupSn(), orderInfo.getLockers().getLockersSn(), 1, 0, serialNum, orderInfo.getPurchaser().getCardInfo().getCardNumber());
							
							String passwd = result.getString("passwd");
							String rfid = result.getString("rfidSn");
							
							List<ProductBatch> productBatchs = entityManager.createQuery("select pb from ProductBatch pb where pb.passwd = :passwd and (pb.orderInformation.transactions = 3 or pb.orderInformation.transactions = 6)").setParameter("passwd", passwd).getResultList();
							serialNum++;
							if (null == productBatchs || productBatchs.size() == 0) {
								productBatch.setRfidSn(rfid);
								productBatch.setPasswd(passwd);
								break;
							}
						}
						
						productBatch.setInsertTime(new Date());
						productBatch.setStatus(0);
						
						JSONObject generalCode = new JSONObject();
						generalCode.accumulate("rfid_code", productBatch.getRfidSn());
						
						generalCodes.add(generalCode);
						
						entityManager.persist(productBatch);
					}
					
					results[0] = generalCodes;

					JSONArray keepWarmCodes = new JSONArray();
					
					for (int i = 0; i < keepWarmNum; i++) {
						ProductBatch productBatch = new ProductBatch();
						productBatch.setOrderInformation(orderInfo);
						
						// 保存包装箱及开柜密码
						while (true) {
							JSONObject result = BarcodeMaker.getCode128(orderInfo.getGroup().getGroupSn(), orderInfo.getLockers().getLockersSn(), 2, 0, serialNum, orderInfo.getPurchaser().getCardInfo().getCardNumber());
							
							String passwd = result.getString("passwd");
							String rfid = result.getString("rfidSn");
							
							List<ProductBatch> productBatchs = entityManager.createQuery("select pb from ProductBatch pb where pb.passwd = :passwd and (pb.orderInformation.transactions = 3 or pb.orderInformation.transactions = 6)").setParameter("passwd", passwd).getResultList();
							serialNum++;
							if (null == productBatchs || productBatchs.size() == 0) {
								productBatch.setRfidSn(rfid);
								productBatch.setPasswd(passwd);
								break;
							}
						}
						
						productBatch.setInsertTime(new Date());
						productBatch.setStatus(0);
						
						JSONObject keepWarmCode = new JSONObject();
						keepWarmCode.accumulate("rfid_code", productBatch.getRfidSn());
						
						keepWarmCodes.add(keepWarmCode);
						
						entityManager.persist(productBatch);
					}
					
					results[1] = keepWarmCodes;

					JSONArray thermostatCodes = new JSONArray();
					
					for (int i = 0; i < thermostatNum; i++) {
						ProductBatch productBatch = new ProductBatch();
						productBatch.setOrderInformation(orderInfo);
						
						// 保存包装箱及开柜密码
						while (true) {
							JSONObject result = BarcodeMaker.getCode128(orderInfo.getGroup().getGroupSn(), orderInfo.getLockers().getLockersSn(), 3, 4, serialNum, orderInfo.getPurchaser().getCardInfo().getCardNumber());
							
							String passwd = result.getString("passwd");
							String rfid = result.getString("rfidSn");
							
							List<ProductBatch> productBatchs = entityManager.createQuery("select pb from ProductBatch pb where pb.passwd = :passwd and (pb.orderInformation.transactions = 3 or pb.orderInformation.transactions = 6)").setParameter("passwd", passwd).getResultList();
							serialNum++;
							if (null == productBatchs || productBatchs.size() == 0) {
								productBatch.setRfidSn(rfid);
								productBatch.setPasswd(passwd);
								break;
							}
						}
						
						productBatch.setInsertTime(new Date());
						productBatch.setStatus(0);
						
						JSONObject thermostatCode = new JSONObject();
						thermostatCode.accumulate("rfid_code", productBatch.getRfidSn());
						
						thermostatCodes.add(thermostatCode);
						
						entityManager.persist(productBatch);
					}
					
					results[2] = thermostatCodes;

					orderInfo.setTransactions(3);
					
					entityManager.merge(orderInfo);
				}
			}
			
			entityManager.flush();
			
			ut.commit();
			
			return results;
		} catch (Exception e) {
			try {
				ut.rollback();
			} catch (Exception e1) {
				logger.error("Data rollback fail!\n" + e1.getMessage());
			} 

			logger.error("Rfid codes fail!\n" + e.getMessage());
			
			return null;
		}
	}
	
	@SuppressWarnings("unchecked")
	public DeliveryPlan planFilter(Integer groupId, Integer lockersId, Integer orderInformationId, Integer productBatchNum, Integer storeMode, Date beginTime, Date endTime, List<DeliveryPlan> deliveryPlans) {

		//拼接语句查询是否已有配送计划
		StringBuffer existPlanSql = new StringBuffer();
		
		existPlanSql.append("select distinct dp from DeliveryPlan dp inner join dp.storageGrid sg left join dp.orderInformation oi where dp.planType = 1 and sg.deleted = 0 and oi.transactions >= 4 and oi.transactions <= 6");
		
		//判断接受数据是否为空
		if (groupId != null && lockersId != null && beginTime != null && endTime != null) {
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(endTime);
			calendar.add(Calendar.DATE, 1);
			
			existPlanSql.append(" and sg.lockers.lockersId = ").append(lockersId);
			existPlanSql.append(" and sg.businessType = 1");
			existPlanSql.append(" and sg.gridType = ").append(storeMode);
			existPlanSql.append(" and dp.beginTime >= '").append(DateTimeHelper.dateTimeToStr(beginTime, DateTimeHelper.DEFAULT_DATE_FORMAT)).append(" 00:00:00'");
			existPlanSql.append(" and dp.endTime <= '").append(DateTimeHelper.dateTimeToStr(calendar.getTime(), DateTimeHelper.DEFAULT_DATE_FORMAT)).append(" 23:59:59'");
		} else {
			return null;
		}
		
		List<DeliveryPlan> existPlanList = entityManager.createQuery(existPlanSql.toString()).getResultList();
		
		if (null != deliveryPlans){
			for (Iterator it = deliveryPlans.iterator(); it.hasNext();) {
				DeliveryPlan deliveryPlan = (DeliveryPlan) it.next();
				if (beginTime.getTime() < deliveryPlan.getBeginTime().getTime() && endTime.getTime() <= deliveryPlan.getBeginTime().getTime()){
					it.remove();
				} else if (beginTime.getTime() >= deliveryPlan.getEndTime().getTime() && endTime.getTime() > deliveryPlan.getEndTime().getTime()){
					it.remove();
				}
			}
		}
		
		if (null != existPlanList){
			if (existPlanList.size() > 0){
				//过滤计划时间
				for (Iterator it = existPlanList.iterator(); it.hasNext();) {
					DeliveryPlan deliveryPlan = (DeliveryPlan) it.next();
					if (beginTime.getTime() < deliveryPlan.getBeginTime().getTime() && endTime.getTime() <= deliveryPlan.getBeginTime().getTime()){
						it.remove();
					} else if (beginTime.getTime() >= deliveryPlan.getEndTime().getTime() && endTime.getTime() > deliveryPlan.getEndTime().getTime()){
						it.remove();
					}
				}
			}
			
			
			
			if (null != deliveryPlans && deliveryPlans.size() > 0) {
				existPlanList.addAll(deliveryPlans);
			}
			
			StringBuffer storageGridSql = new StringBuffer();
			storageGridSql.append("select sg from StorageGrid sg where sg.deleted = 0 and sg.gridType = ");
			storageGridSql.append(storeMode).append(" and sg.lockers.lockersId = ").append(lockersId);
			storageGridSql.append(" and sg.businessType = 1 ");
			
			if (existPlanList.size() > 0){
				storageGridSql.append(" and sg.storageGridId not in (");
				
				for (int i = 0; i < existPlanList.size(); i++){
					storageGridSql.append(existPlanList.get(i).getStorageGrid().getStorageGridId());
					if (i < existPlanList.size() - 1)
						storageGridSql.append(",");
				}
				
				storageGridSql.append(")");
			}
			
			//获取可用仓门数据
			List<StorageGrid> storageGridList = entityManager.createQuery(storageGridSql.toString()).getResultList();
			
			if (storageGridList.size() > 0){
				if (storageGridList.size() >= productBatchNum){//验证仓门是否够用
					/*String productBatchSQL = "select pb from ProductBatch pb where pb.deleted = 0 and pb.orderInformation.orderInformationId = " + orderInformationId + " and pb.storeMode =" + storeMode;
					List<ProductBatch> productBatchList = entityManager.createQuery(productBatchSQL).getResultList();
					if (productBatchList.size() >= productBatchNum){*/
						//for (int i = 0; i < productBatchNum; i++){
							DeliveryPlan deliveryPlan = new DeliveryPlan();
							deliveryPlan.setBeginTime(beginTime);
							deliveryPlan.setEndTime(endTime);
							deliveryPlan.setPlanType(1);
							deliveryPlan.setStorageGrid(storageGridList.get(0));
							deliveryPlan.setLockers(storageGridList.get(0).getLockers());
							deliveryPlan.setPublish(false);
							deliveryPlan.setInsertTime(new Date());
							OrderInformation orderInformation = new OrderInformation();
							orderInformation.setOrderInformationId(orderInformationId);
							deliveryPlan.setOrderInformation(orderInformation);
							return deliveryPlan;
						//}
					//}
				} else {
					return null;
				}
			} else {
				return null;
			}
		}
		
		return null;
	}
}
